﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.ComponentModel;
using Microsoft.Win32;

namespace Nizm0.QOT
{

    [Serializable]
    public sealed class Settings// : ISerializable
    {

        #region __CodeSorter_unsorted
        //public Library.Objects.RegexPatern[] PaternTab
        //{
        //    get { return _paternList.ToArray(); }
        //    set { _paternList = value.ToList(); }
        //}






        //[NonSerialized]
        //private Objects.IErrorLog _errorLog;
        //[NonSerialized]
        //private Objects.IStatusLog _statusLog;

        //[NonSerialized]
        //public string ProjectLocalization;
        //[NonSerialized]
        //public string ProcedureLocalization;





























        //#region ISerializable Members

        //public void GetObjectData(SerializationInfo info, StreamingContext context)
        //{
        //    throw new NotImplementedException();
        //}

        //#endregion
        #endregion

        [NonSerialized]
        private ICSharpCode.AvalonEdit.Highlighting.IHighlightingDefinition _textHighlighting;// = ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.HighlightingNames.ToList<string>();
        
        public ICSharpCode.AvalonEdit.Highlighting.IHighlightingDefinition TextHighlighting
        {
            get { return _textHighlighting; }
            set { _textHighlighting = value; }
        }

        private static volatile Settings _instance;
        public static Settings Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (syncRoot)
                    {
                        if (_instance == null)
                        {
                            _instance = new Settings();
                            Settings.Instance.DeSerialize();
                        }
                    }
                }

                return _instance;
            }
        }

        private static object syncRoot = new Object();

        [NonSerialized]
        private List<Assembly> _asseblies = new List<Assembly>();

        [ReadOnlyAttribute(true)]
        public string AssemblyName
        {
            get
            {
                return Assembly.GetEntryAssembly().GetName().Name.ToString();
            }
        }

        [ReadOnlyAttribute(true)]
        public string AssemblyProduct
        {
            get
            {
                object[] attributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                if (attributes.Length == 0)
                {
                    return "";
                }
                return ((AssemblyProductAttribute)attributes[0]).Product;
            }
        }

        [ReadOnlyAttribute(true)]
        public string AssemblyTitle
        {
            get
            {
                object[] attributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
                if (attributes.Length > 0)
                {
                    AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
                    if (titleAttribute.Title != "")
                    {
                        return titleAttribute.Title;
                    }
                }
                return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase);
            }
        }

        [ReadOnlyAttribute(true)]
        public string AssemblyVersion
        {
            get
            {
                return Assembly.GetEntryAssembly().GetName().Version.ToString();
            }
        }

        //public System.Windows.Forms.Form Main = Assembly.GetEntryAssembly().

        //TODO Move to ProjectSettings
        public int CommandTimeout = 600;//in miliseconds

        public int ConectionTimeout = 5;//in miliseconds

        private string _defoultProjectLocation;
        public string DefoultProjectLocation
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_defoultProjectLocation) || !Directory.Exists(_defoultProjectLocation))
                {
                    _defoultProjectLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\QOT\\Projects";
                    if (!Directory.Exists(_defoultProjectLocation))
                        Directory.CreateDirectory(_defoultProjectLocation);
                }
                return _defoultProjectLocation;
            }
            set
            {
                _defoultProjectLocation = value;
            }
        }

        public bool Excel2007 = true;
        public System.Drawing.Point MainPosition = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Location;

        //public System.Windows.Forms.Screen scrn;
        //System.Drawing.Rectangle wa = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
        public System.Drawing.Size MainSize = new System.Drawing.Size((System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Size.Width / 3) * 2, (System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Size.Height / 3) * 2);

        public System.Windows.Forms.FormWindowState MainWindowState;// = new System.Windows.Forms.WindowsFormsSection();
        public int MaxRouningProcess = 5;

        [NonSerialized]
        private List<Library.Objects.IOption> _optionList = new List<Library.Objects.IOption>();

        private List<Library.Objects.RegexPatern> _paternList = new List<Library.Objects.RegexPatern>();
        //[NonSerializedAttribute]
        public List<Library.Objects.RegexPatern> PaternList
        {
            get { return _paternList; }
            //set { _paternList = value; }
        }

        [NonSerialized]
        private string _programLocalization;

        [ReadOnlyAttribute(true)]
        public string ProgramLocalization
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_programLocalization))
                    _programLocalization = GetProgramLocalization();
                return _programLocalization;
            }
        }

        private string _settingsLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\QOT\\Settings\\";

        public string SettingsLocation
        {
            get
            {
                if (!Directory.Exists(_settingsLocation)) Directory.CreateDirectory(_settingsLocation);
                return _settingsLocation;
            }
            set { _settingsLocation = value; }
        }

        [NonSerialized]
        private Library.Objects.ProjectSettings _projectSettings;

        public Library.Objects.ProjectSettings ProjectSettings
        {
            get
            {
                if (_projectSettings == null)
                    _projectSettings = Library.Objects.ProjectSettings.Instance;
                return _projectSettings;
            }
            set { _projectSettings = value; }
        }

        public Boolean ResultWordWrap = false;

        //public List<System.Windows.Forms.Screen> scrlist = System.Windows.Forms.Screen.AllScreens.ToList();
        public int ScreenId = 0;

        private Settings()
        {
            _asseblies.Add(Assembly.GetExecutingAssembly());
            _asseblies.Add(Assembly.GetEntryAssembly());
            //_paternList = new List<Library.Objects.RegexPatern>();
            //GetProgramLocalization();
        }

        [ReadOnlyAttribute(true)]
        public void AssociateFile()
        {
            try
            {
                RegistryKey RegKey = Registry.ClassesRoot.CreateSubKey(Library.Objects.ProjectSettings.Instance.FileExtension);
                RegKey.SetValue("", Library.Objects.ProjectSettings.Instance.FileTypeName);
                RegKey.Close();

                RegKey = Registry.ClassesRoot.CreateSubKey(Library.Objects.ProjectSettings.Instance.FileTypeName);
                RegKey.SetValue("", AssemblyProduct);
                RegKey.Close();

                //Create open command for qot files

                RegKey = Registry.ClassesRoot.CreateSubKey(Library.Objects.ProjectSettings.Instance.FileTypeName + "\\" + "Shell" + "\\" + "Open");
                RegKey = RegKey.CreateSubKey("Command");
                //Set the application for handling the open command and pass
                //the file path as a parameter
                RegKey.SetValue("", "\"" + ProgramLocalization + "\\" + AssemblyName + "\"" + " \"%L\"");//set runing aplication
                RegKey.Close();

                //Associate icon for qot files

                RegKey = Registry.ClassesRoot.CreateSubKey(Library.Objects.ProjectSettings.Instance.FileTypeName + "\\" + "DefaultIcon");

                string s1 = Assembly.GetEntryAssembly().CodeBase;
                RegKey.SetValue("", s1);//set icon //ProgramLocalization + "\\" + AssemblyName + ".exe"
                RegKey.Close();
            }
            catch (UnauthorizedAccessException ex)
            {
                System.Windows.Forms.MessageBox.Show(string.Format("Register Exception\n{0}\nRun program as Administrator.", ex.Message), "Unauthorized Access Exception", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        private Settings DeSerialize()
        {
            //if (!Directory.Exists(ProjectSettings.ProjectLocation + "\\Queries\\AdditionalData\\")) Directory.CreateDirectory(ProjectSettings.ProjectLocation + "\\Queries\\AdditionalData\\");
            if (!File.Exists(this.SettingsLocation + "\\Settings.ini"))
                this.Serialize();
            StreamReader str = new StreamReader(this.SettingsLocation + "\\Settings.ini", Encoding.UTF8, false);
            Settings deserialSettings = null;
            try
            {
                byte[] arrayByte = Convert.FromBase64String(str.ReadToEnd());
                using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream(arrayByte))
                {
                    BinaryFormatter b = new BinaryFormatter();
                    deserialSettings = (Settings)b.Deserialize(ms1);

                    Settings.Instance.MaxRouningProcess = deserialSettings.MaxRouningProcess;
                    Settings.Instance.ResultWordWrap = deserialSettings.ResultWordWrap;
                    Settings.Instance.MainWindowState = deserialSettings.MainWindowState;
                    if (Settings.Instance.MainWindowState == System.Windows.Forms.FormWindowState.Normal)
                    {
                        Settings.Instance.MainSize = deserialSettings.MainSize;
                        Settings.Instance.MainPosition = deserialSettings.MainPosition;
                    }
                    Settings.Instance.CommandTimeout = deserialSettings.CommandTimeout;
                    Settings.Instance.ConectionTimeout = deserialSettings.ConectionTimeout;
                    Settings.Instance.DefoultProjectLocation = string.IsNullOrWhiteSpace(deserialSettings.DefoultProjectLocation) ? Settings.Instance.DefoultProjectLocation : Settings.Instance.DefoultProjectLocation;
                    Settings.Instance._paternList = deserialSettings.PaternList == null ? Settings.Instance._paternList : deserialSettings.PaternList;
                }
            }
            catch (SerializationException exs)
            {
                //str.Close();
                if (File.Exists(this.SettingsLocation + "\\Settings.ini.old")) File.Delete(this.SettingsLocation + "\\Settings.ini.old");
                File.Copy(this.SettingsLocation + "\\Settings.ini", this.SettingsLocation + "\\Settings.ini.old");
                File.Delete(this.SettingsLocation + "\\Settings.ini");
                Settings.Instance.DeSerialize();
            }
            catch (Exception ex)
            {
                //ReportError(this, ex);
            }
            finally
            {
                str.Close();
            }
            return deserialSettings;
        }

        public List<Library.Objects.IOption> GetOptions()
        {
            //var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            //var types =
            //    Assembly.GetEntryAssembly().GetTypes()
            //   .Where(m => m.IsClass && m.GetInterface("IOption") != null);
            foreach (Assembly item in _asseblies)
            {
                var instances = from t in item.GetTypes()
                                where t.GetInterfaces().Contains(typeof(Library.Objects.IOption))
                                         && t.GetConstructor(Type.EmptyTypes) != null
                                select Activator.CreateInstance(t) as Library.Objects.IOption;

                foreach (var instance in instances)
                {
                    _optionList.Add(instance);
                }
            }
            return _optionList;
        }

        private string GetProgramLocalization()
        {
            return System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
        }

        public bool OpenNewWindow(System.Windows.Forms.Form form)
        {
            return false;
        }

        public void Load()
        {
            //Settings set = DeSerialize();

        }

        public void Save()
        {
            Serialize();
        }

        private void Serialize()
        {
            //if (!Directory.Exists(this.SettingsLocation)) Directory.CreateDirectory(this.SettingsLocation + "\\Queries\\AdditionalData\\");
            StreamWriter str = new StreamWriter(this.SettingsLocation + "\\Settings.ini", false, Encoding.UTF8);
            try
            {
                string serialString = null;
                using (System.IO.MemoryStream ms1 = new System.IO.MemoryStream())
                {
                    BinaryFormatter b = new BinaryFormatter();
                    b.Serialize(ms1, Settings.Instance);//Settings.Instance
                    byte[] arrayByte = ms1.ToArray();
                    serialString = Convert.ToBase64String(arrayByte);
                }
                //return serialString;
                str.Write(serialString);
                str.Close();


                if (File.Exists(this.SettingsLocation + "\\Settings.ini.buckup")) File.Delete(this.SettingsLocation + "\\Settings.ini.buckup");
                File.Copy(this.SettingsLocation + "\\Settings.ini", this.SettingsLocation + "\\Settings.ini.buckup");
                FileInfo f = new FileInfo(this.SettingsLocation + "\\Settings.ini.buckup");
                f.Attributes |= FileAttributes.Hidden;
            }
            catch (Exception ex)
            {
                //ReportError(this, ex);
            }
            finally
            {
                str.Close();
            }
        }
    }
}
